//
//  IMChatInputView.m
//  MLIM
//
//  Created by molon on 15/6/25.
//  Copyright (c) 2015年 molon. All rights reserved.
//

#import "IMChatInputView.h"
#import "IMCommon.h"
#import <HPGrowingTextView.h>
#import <MLTipsAudioRecordButton.h>
#import <MLInputDodger.h>

#define kAudioDirName @"MLIMRecordAudio"

#define kTextViewBackImageViewYMargin 6.0f
#define kTextViewYMargin 1.0f
@interface IMChatInputView()<HPGrowingTextViewDelegate>

//这个其实才是实际的那个条条
@property (nonatomic, strong) UIView *inputPanel;
@property (nonatomic, strong) UIImageView *panelBackgroundImageView;
@property (nonatomic, strong) UIImageView *textViewBakgroundImageView;
@property (nonatomic, strong) UIButton *voiceSwitchButton;
@property (nonatomic, strong) UIButton *moreSwitchButton;

//TODO: 这个输入多行内容偶尔会跳动，这个需要解决下
@property (nonatomic, strong) HPGrowingTextView *textView;
@property (nonatomic, strong) MLTipsAudioRecordButton *audioRecordButton;

@property (nonatomic, assign) UIViewAnimationCurve animationCurve;
@property (nonatomic, assign) CFTimeInterval animationDuration;

@property (nonatomic, assign) UIView<IMChatInputBottomViewDelegate> *moreView;

//合适的text高度
@property (nonatomic, assign) CGFloat textPreferredHeight;

//除去inputPanel的合适高度，其实说白了就是表情和更多区域或者键盘的合适高度
@property (nonatomic, assign) CGFloat preferredHeightWithoutInputPanel;

//这个是为了preferredHeight没改变的时候，block被执行，做无用功，甚至在极端情况下产生动画重复调用
@property (nonatomic, assign) CGFloat lastPreferredHeight;
//这个在set mode方法里有解释
@property (nonatomic, assign) BOOL ignoreThisResignForKeyboardHide;

//用来保证set keyboard mode只有keyboardWillShow调用的才有效。
//之前一直是靠isFirstResponder来判断，换用这个是为了解决iOS8下的键盘在keyWindow切换之后的键盘再次弹起但是firstResponder有误的BUG
@property (nonatomic, assign) BOOL dontCheckIsFirstResponder;

@end

@implementation IMChatInputView

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.lastPreferredHeight = -1;
        
        self.animationCurve = 7; //这是ios7键盘的默认curve,先给了准没错
        self.animationDuration = .25f;
        
        [self addSubview:self.inputPanel];
        [self addSubview:self.moreView];
        
        //监控键盘
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];
        self.enableModes = IMChatInputEnableModeAll;
        self.inputMode = IMChatInputModeNone;
    }
    return self;
}

-(instancetype)initWithMoreView:(UIView<IMChatInputBottomViewDelegate> *)moreView
{
    self = [self init];
    if (self) {
        if (self.moreView) {
            [self.moreView removeFromSuperview];
        }
        self.moreView = moreView;
        [self addSubview:moreView];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification object:nil];
    
    DLOG(@"dealloc %@",NSStringFromClass([self class]));
}

#pragma mark - getter
- (UIView *)inputPanel
{
    if (!_inputPanel) {
        _inputPanel = [UIView new];
        [_inputPanel addSubview:self.panelBackgroundImageView];
        [_inputPanel addSubview:self.voiceSwitchButton];
        [_inputPanel addSubview:self.textViewBakgroundImageView];
        [_inputPanel addSubview:self.moreSwitchButton];
        [_inputPanel addSubview:self.audioRecordButton];
    }
    return _inputPanel;
}

- (UIImageView *)panelBackgroundImageView
{
    if (!_panelBackgroundImageView) {
        UIImageView *imageView = [[UIImageView alloc]init];
        imageView.contentMode = UIViewContentModeScaleToFill;
        imageView.image =  [IMIMG(@"输入面板背景") resizableImageWithCapInsets:UIEdgeInsetsMake(5, 0, 0, 0)];
        
        _panelBackgroundImageView = imageView;
    }
    return _panelBackgroundImageView;
}

- (UIImageView *)textViewBakgroundImageView
{
    if (!_textViewBakgroundImageView) {
        UIImageView *imageView = [[UIImageView alloc]init];
        imageView.contentMode = UIViewContentModeScaleToFill;
        imageView.image =  [IMIMG(@"输入框背景") resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5)];
        imageView.userInteractionEnabled = YES;
        
        [imageView addSubview:self.textView];
        
        _textViewBakgroundImageView = imageView;
    }
    return _textViewBakgroundImageView;
}

- (UIButton *)voiceSwitchButton
{
    if (!_voiceSwitchButton) {
        UIButton *button = [[UIButton alloc]init];
        button.exclusiveTouch = YES;
        [button addTarget:self action:@selector(voiceSwitchButtonClicked) forControlEvents:UIControlEventTouchUpInside];
        
        _voiceSwitchButton = button;
    }
    return _voiceSwitchButton;
}

- (MLTipsAudioRecordButton *)audioRecordButton
{
    if (!_audioRecordButton) {
        MLAudioRecordWeChatStyleTipsView *tipsView = [MLAudioRecordWeChatStyleTipsView new];
        MLTipsAudioRecordButton *button = [[MLTipsAudioRecordButton alloc]initWithMLAudioRecordTipsView:tipsView];
        button.titleLabel.font = [UIFont boldSystemFontOfSize:16.0f];
        [button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
        
        WEAKSELF
        [button setNewFilePathBlock:^NSURL *(MLAudioRecordButton *button) {
            NSSearchPathDirectory searchDir = NSDocumentDirectory;
            NSSearchPathDomainMask searchMask = NSUserDomainMask;
            
            //这里检测是否存在此文件夹，不存在就建立
            NSArray *paths = NSSearchPathForDirectoriesInDomains(searchDir, searchMask, YES);
            NSString *audioDir = [[paths firstObject] stringByAppendingPathComponent:kAudioDirName];
            
            if (![[NSFileManager defaultManager] fileExistsAtPath:audioDir]){
                if([[NSFileManager defaultManager] createDirectoryAtPath:audioDir withIntermediateDirectories:YES attributes:nil error:NULL]){
                    [[NSFileManager defaultManager]addSkipBackupAttributeToItemAtPath:audioDir];
                }
            }
            
            //设置一个新文件名字
            time_t curUnixTime = 0;
            time(&curUnixTime);
            NSString *key = [NSString stringWithFormat:@"%ld-%ld", curUnixTime,(NSInteger)(arc4random()%10000)];
            MLURL *url = [MLURL fileURLWithPath:[kAudioDirName stringByAppendingPathComponent:key] isDirectory:NO searchPathDirectory:searchDir searchPathDomainMask:searchMask];
            return url;
        }];
        [button setBackgroundImageBlock:^UIImage *(MLAudioRecordButtonStatus status, MLAudioRecordButton *button) {
            UIImage *image = nil;
            if (status == MLAudioRecordButtonStatusNormal) {
                image = IMIMG(@"录音按钮背景");
            }else{
                image = IMIMG(@"录音按钮按下背景");
            }
            return [image resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
        }];
        [button setTitleBock:^NSString *(MLAudioRecordButtonStatus status, MLAudioRecordButton *button) {
            return @[@"按住 说话",@"松开 结束",@"松开 取消"][status];
        }];
        
        [button setDidRecordAudioBlock:^(NSURL *filePath, NSTimeInterval duration, MLAudioRecordButton *button) {
            STRONGSELF
            if (sSelf.sendAudioMessageBlock) {
                sSelf.sendAudioMessageBlock(filePath,duration);
            }
        }];
        
        _audioRecordButton = button;
    }
    return _audioRecordButton;
}

- (HPGrowingTextView *)textView
{
    if (!_textView) {
        HPGrowingTextView *textView = [HPGrowingTextView new];
        textView.clipsToBounds = YES;
        textView.backgroundColor = [UIColor clearColor];
        textView.enablesReturnKeyAutomatically = YES;
        textView.font = [UIFont systemFontOfSize:16.0f];
        textView.delegate = self;
        textView.returnKeyType = UIReturnKeySend;
        textView.exclusiveTouch = YES;
        
        textView.minNumberOfLines = 1;
        textView.maxNumberOfLines = 5;
        
        _textView = textView;
    }
    return _textView;
}

- (UIButton *)moreSwitchButton
{
    if (!_moreSwitchButton) {
        UIButton *button = [[UIButton alloc]init];
        button.exclusiveTouch = YES;
        [button addTarget:self action:@selector(moreSwitchButtonClicked) forControlEvents:UIControlEventTouchUpInside];
        
        _moreSwitchButton = button;
    }
    return _moreSwitchButton;
}


#pragma mark - setter
- (void)setEnableModes:(IMChatInputEnableMode)enableModes
{
    _enableModes = enableModes;
    
    self.voiceSwitchButton.hidden = !(enableModes&IMChatInputEnableModeVoice);
    self.moreSwitchButton.hidden = !(enableModes&IMChatInputEnableModeMore);
    
    [self setNeedsLayout];
}

- (void)setInputMode:(IMChatInputMode)inputMode
{
    if (inputMode==IMChatInputModeKeyboard) {
        //这个判断用来保证set keyboard mode一定是keyboardWillShow方法调用的才有效，如果不是，就用becomeFirstResponder去激活keyboardWillShow方法去调用，主要是为了从其中取一些键盘高度和动画值数据
        if (!self.dontCheckIsFirstResponder) {
            [self.textView becomeFirstResponder];
            return;
        }
    }
    
    IMChatInputMode origInputViewMode = _inputMode;
    
    _inputMode = inputMode;
    
    switch (inputMode) {
        case IMChatInputModeNone:
            self.preferredHeightWithoutInputPanel = 0;
            break;
        case IMChatInputModeKeyboard:
            //这里的preferredHeightWithoutInputPanel会在keyboardWillShow里设置了。
            break;
        case IMChatInputModeVoice:
            self.preferredHeightWithoutInputPanel = 0;
            break;
        case IMChatInputModeMore:
            self.preferredHeightWithoutInputPanel = [self.moreView preferredHeight];
            [self bringSubviewToFront:self.moreView];
            break;
        default:
            break;
    }
    
    
    //图标设置
    self.audioRecordButton.hidden = !(inputMode==IMChatInputModeVoice);
    self.textView.hidden = (inputMode==IMChatInputModeVoice);
    self.textViewBakgroundImageView.hidden = self.textView.hidden;
    
    [self.voiceSwitchButton setImage:(inputMode==IMChatInputModeVoice)?IMIMG(@"键盘"):IMIMG(@"语音") forState:UIControlStateNormal];
    [self.moreSwitchButton setImage:(inputMode==IMChatInputModeMore)?IMIMG(@"键盘"):IMIMG(@"更多") forState:UIControlStateNormal];
    
    
    //不是键盘就必须消失它
    if (inputMode!=IMChatInputModeKeyboard) {
        if ([self.textView isFirstResponder]) {
            //这里是为了防止resign触发了keyboardWillHide
            //而keyboardWillHide里有set IMChatInputModeNone操作，就会让这次set mode无效了。
            self.ignoreThisResignForKeyboardHide = YES;
            [self.textView resignFirstResponder];
            self.ignoreThisResignForKeyboardHide = NO;
        }
    }
    if ([self preferredHeight]!=self.lastPreferredHeight) {
        self.lastPreferredHeight = [self preferredHeight];
        if (self.preferredHeightChangedBlock) {
            //如果之前就是键盘模式，那就不需要动画了
            //因为之前就是键盘模式的话，再次走到这里说明只是键盘高度的改变，而iOS7+上键盘在已经显示的情况下高度改变是没有动画的，所以我们这里也不应该有，否则效果很差
            BOOL animated = !(inputMode==IMChatInputModeKeyboard&&origInputViewMode==IMChatInputModeKeyboard);
            self.preferredHeightChangedBlock(self,animated,self.animationCurve,self.animationDuration);
            
            if (animated) {
                [self animateLayoutIfNeed];
            }
        }
    }
}

#pragma mark - event
- (void)voiceSwitchButtonClicked
{
    self.inputMode = (self.inputMode==IMChatInputModeVoice)?IMChatInputModeKeyboard:IMChatInputModeVoice;
}

- (void)moreSwitchButtonClicked
{
    self.inputMode = (self.inputMode==IMChatInputModeMore)?IMChatInputModeKeyboard:IMChatInputModeMore;
}


#pragma mark - height
- (CGFloat)inputPanelHeight
{
    if (self.inputMode == IMChatInputModeVoice) {
        return kMinInputPanelHeight;
    }
    
    CGFloat height = self.textPreferredHeight+kTextViewYMargin*2+kTextViewBackImageViewYMargin*2;
    
    return MAX(height, kMinInputPanelHeight);
}

- (CGFloat)preferredHeight
{
    return [self inputPanelHeight]+self.preferredHeightWithoutInputPanel;
}


#pragma mark - layout
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    self.inputPanel.frame = CGRectMake(0, 0, self.frameWidth, [self inputPanelHeight]);
    self.panelBackgroundImageView.frame = self.inputPanel.bounds;
    
    CGFloat panelHeight = self.inputPanel.frameHeight;
    
#define kButtonBottomMargin 7.5f
#define kButtonSideLength 35.0f
    if (!self.voiceSwitchButton.hidden) {
        self.voiceSwitchButton.frame = CGRectMake(0, panelHeight-kButtonBottomMargin-kButtonSideLength, kButtonSideLength, kButtonSideLength);
    }else{
        self.voiceSwitchButton.frame = CGRectMake(0, 0, 0, 0);
    }
    
    if (!self.moreSwitchButton.hidden) {
        self.moreSwitchButton.frame = CGRectMake(self.inputPanel.frameWidth-kButtonSideLength, self.voiceSwitchButton.frameY, kButtonSideLength, kButtonSideLength);
    }else{
        self.moreSwitchButton.frame = CGRectMake(self.inputPanel.frameWidth, 0, 0, 0);
    }
    
#define kXSpcing 5.0f
    CGFloat textViewBackgroundImageViewHeight = self.inputPanel.frameHeight-kTextViewBackImageViewYMargin*2;
    self.textViewBakgroundImageView.frame = CGRectMake(self.voiceSwitchButton.frameRight+kXSpcing, kTextViewBackImageViewYMargin, self.moreSwitchButton.frameX-self.voiceSwitchButton.frameRight-kXSpcing*2, textViewBackgroundImageViewHeight);
    
    self.textView.frame = CGRectInset(self.textViewBakgroundImageView.bounds, 3.0f, kTextViewYMargin);
    
    self.audioRecordButton.frame = self.textViewBakgroundImageView.frame;
    
    self.moreView.frame = CGRectMake(0, self.inputPanel.frameBottom, self.frameWidth, [self.moreView preferredHeight]);
}

#pragma mark - Keyboard
- (void)keyboardWillShow:(NSNotification *)notification
{
    //iOS8下，例如alert显示然后恢复之后，键盘重新出现这里textView不会被认为是firstResponder，所以我们不能用其判断
    //虽然会造成其他输入引起键盘弹起，这里我们也会执行的问题，但是总好过有BUG强
//    if (![self.textView isFirstResponder]) {
//        return;
//    }
    if (![[[MLInputDodger dodger]firstResponderView]isEqual:self.textView.internalTextView]) {
        return;
    }
    
    NSDictionary *userInfo = [notification userInfo];
    CGRect convertedRect = [self convertRect:[userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
    self.preferredHeightWithoutInputPanel = convertedRect.size.height;
    
    self.animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey]doubleValue];
    self.animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    
    self.dontCheckIsFirstResponder = YES;
    self.inputMode = IMChatInputModeKeyboard;
    self.dontCheckIsFirstResponder = NO;
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    if (self.ignoreThisResignForKeyboardHide) {
        self.ignoreThisResignForKeyboardHide = NO;
        return;
    }
    
    //到这里就说明是非本类内部产生的键盘隐藏事件，直接设置为None即可
    NSDictionary *userInfo = [notification userInfo];
    
    self.animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey]doubleValue];
    self.animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    
    self.inputMode = IMChatInputModeNone;
}


#pragma mark - textView delegate
- (BOOL)growingTextView:(HPGrowingTextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if([text isEqualToString:@"\n"]) { //单个按回车会被认作点击发送
        if (![NSString IsNilOrEmpty:textView.text]) {
            [self sendMessage];
        }else{
            if (textView.text.length>0) {
                SHOW_SIMPLE_TIPS(@"不能发送空白消息");
                self.textView.text = @"";
                //TODO: 这个时候的return key不会被disable,微信也是如此，有空再解决 iOS7下
            }
        }
        return NO;
    };
    
    return YES;
}

- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height
{
    self.textPreferredHeight = height;
    //注意kMinInputPanelHeight下的textView默认高度一定要刚好适配内容为一行的高度，否则可能会造成键盘模式下切换中英文键盘高度改变引起的回调block动画为NO，而这个就变成了YES，造成不好的效果。
    
    if ([self preferredHeight]!=self.lastPreferredHeight) {
        self.lastPreferredHeight = [self preferredHeight];
        
        if (self.preferredHeightChangedBlock) {
            self.preferredHeightChangedBlock(self,YES,self.animationCurve,self.animationDuration);
            [self animateLayoutIfNeed];
        }
    }
}

#pragma mark - other common
- (void)animateLayoutIfNeed
{
    [self setNeedsLayout];
    
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:self.animationDuration];
    [UIView setAnimationCurve:self.animationCurve];
    [UIView setAnimationBeginsFromCurrentState:YES];
    
    [self layoutIfNeeded];
    
    [UIView commitAnimations];
}

- (void)sendMessage
{
    NSAssert(![NSString IsNilOrEmpty:self.textView.text], @"不能发送空白消息");
    
    if (self.sendContentMessageBlock) {
        self.sendContentMessageBlock(self.textView.text);
    }
    self.textView.text = @"";
    //TODO: 这个时候的return key不会被disable,微信也是如此，有空再解决 iOS7下
}


- (void)stopIfRecording
{
    [self.audioRecordButton stopRecordingWithCancel:NO];
}

@end
